import {
  HttpErrorResponse,
  HttpEvent,
  HttpHandler,
  HttpInterceptor,
  HttpRequest,
  HttpResponse,
} from '@angular/common/http';
import { Injectable, Injector } from '@angular/core';
import { Router } from '@angular/router';
import { Observable, of, throwError } from 'rxjs';
import { catchError, mergeMap } from 'rxjs/operators';
import { environment } from 'src/environments/environment';
import { ToastController } from '@ionic/angular';
import { CommonService } from '../common/common.service';

const CODEMESSAGE = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队（异步任务）。',
  204: '删除数据成功。',
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限（令牌、用户名、密码错误）。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。',
  417: '不能包含html的危险字符',
  505: '可能是口令较弱，请修改密码',
};

/**
 * 默认HTTP拦截器，其注册细节见 `app.module.ts`
 */
@Injectable()
export class DefaultInterceptor implements HttpInterceptor {
  constructor(private injector: Injector,private toastController: ToastController,private commonService: CommonService) {}

  private goTo(url: string) {
    setTimeout(() => this.injector.get(Router).navigateByUrl(url));
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // 统一加上服务端前缀
    let url = req.url;
    if (!url.startsWith('https://') && !url.startsWith('http://') && !url.startsWith('./')) {
      url = this.trim(environment.SERVER_URL) + '/' + this.trim(url);
    }

    console.log(url);
    req=req.clone( {url} );

    return next.handle(req).pipe(
      mergeMap((event: any) => {
        // 允许统一对请求错误处理
        if (event instanceof HttpResponse) {
          return this.handleData(event);
        }
        // 若一切都正常，则后续操作
        return of(event);
      }),
      catchError((err: HttpErrorResponse) => this.handleData(err)),
    );
  }

  private trim(value: string) {
    return value.replace(/^(\s|\/)+|(\s|\/)+$/g, '');
  }

  private handleData(event: HttpResponse<any> | HttpErrorResponse): Observable<any> {
    // 业务处理：一些通用操作
    switch (event.status) {
      case 200:
        break;
      case 401: // 未登录状态码
        this.commonService.presentToast(CODEMESSAGE[401]);
        this.goTo('login');
        break;
      case 400:
        this.commonService.presentToast(CODEMESSAGE[400]);
        break;
      case 403:
        this.commonService.presentToast(CODEMESSAGE[403]);
        break;
      case 404:
        this.commonService.presentToast(CODEMESSAGE[404]);
        break;
      case 505:
        this.commonService.presentToast(CODEMESSAGE[505]);
        this.goTo('');
        break;
      case 417:
        this.commonService.presentToast(CODEMESSAGE[417]);
        break;
      case 500:
        if (event instanceof HttpErrorResponse) {
          let msg = event.message;
          if (event.error) {
            const result = event.error as HttpResult;
            msg = this.getErrorMessage(result);
            this.presentToast(msg);
          }
        }
        break;
      default:
        if (event instanceof HttpErrorResponse) {
          console.warn('未可知错误，可能由于后端不支持CORS或无效配置引起', event);
          this.presentToast(event.message);
        }
        break;
    }
    if (event instanceof HttpErrorResponse) {
      return throwError(event);
    } else {
      return of(event);
    }
  }

  /**
   * 获取-失败响应消息
   * @param result 响应结果
   */
  private getErrorMessage(result: HttpResult): string {
    let msg = '';
    if (!result || result.success) {
      return msg;
    }
    const error = result.error;
    // 后台验证错误消息
    // tslint:disable-next-line: prefer-conditional-expression
    if (error.validationErrors && Array.isArray(error.validationErrors)) {
      msg = error.validationErrors[0].message;
    } else {
      msg = error.message || error.details;
    }
    return msg;
  }

  // Toast消息提示
  async presentToast(msg:string) {
    const toast = await this.toastController.create({
      message: msg,
      duration: 5000
    });
    toast.present();
  }


}



/**
 * http响应返回结果
 */
export class HttpResult {
  success: boolean;
  result?: object;
  error?: {
    code?: number;
    message?: string;
    details?: string;
    validationErrors?: [{ message?: string; members?: string[] }];
  };
  unAuthorizedRequest?: boolean;
  constructor() {}
}
